home *** CD-ROM | disk | FTP | other *** search
- /*
- game.c
-
- For TuxMath
- The main game loop!
-
- by Bill Kendrick
- bill@newbreedsoftware.com
- http://www.newbreedsoftware.com/
-
-
- Part of "Tux4Kids" Project
- http://www.tux4kids.org/
-
- August 26, 2001 - September 7, 2001
- */
-
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <SDL.h>
- #ifndef NOSOUND
- #include <SDL_mixer.h>
- #endif
- #include <SDL_image.h>
- #include "game.h"
- #include "images.h"
- #include "setup.h"
- #include "sounds.h"
- #include "playsound.h"
-
-
- #define FPS (1000 / 15) /* 15 fps max */
-
- #define CITY_EXPL_START 3 * 5 /* Must be mult. of 5 (number of expl frames) */
- #define COMET_EXPL_START 2 * 2 /* Must be mult. of 2 (number of expl frames) */
- #define ANIM_FRAME_START 4 * 2 /* Must be mult. of 2 (number of tux frames) */
- #define GAMEOVER_COUNTER_START 75
- #define LEVEL_START_WAIT_START 20
- #define LASER_START 5
-
-
-
- /* Local (to game.c) 'globals': */
-
- int wave, speed, score, pre_wave_score, num_attackers;
- int digits[3];
- comet_type comets[MAX_COMETS];
- city_type cities[NUM_CITIES];
- laser_type laser;
- SDL_Surface * bkgd;
- int last_bkgd;
-
-
-
- /* Local function prototypes: */
-
- void reset_level(void);
- void add_comet(void);
- void draw_nums(char * str, int x, int y);
- void draw_numbers(char * str, int x);
- int pause_game(void);
- void draw_line(int x1, int y1, int x2, int y2, int r, int g, int b);
- void putpixel(SDL_Surface * surface, int x, int y, Uint32 pixel);
- void draw_console_image(int i);
- void add_score(int inc);
-
-
-
- /* --- MAIN GAME FUNCTION!!! --- */
-
- int game(void)
- {
- int i, j, num, img, done, quit, frame, lowest, lowest_y, kx, ky,
- tux_img, old_tux_img, tux_pressing, tux_anim, tux_anim_frame,
- tux_same_counter, level_start_wait, num_cities_alive, doing_answer,
- num_comets_alive, paused, demo_countdown, picked_comet, answer_digit,
- gameover;
- SDL_Event event;
- Uint32 last_time, now_time;
- SDLKey key;
- SDL_Rect src, dest;
- char str[64];
-
-
- /* Clear window: */
-
- SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
- SDL_Flip(screen);
-
-
- /* --- MAIN GAME LOOP: --- */
-
- done = 0;
- quit = 0;
-
-
- /* Prepare to start the game: */
-
- wave = 1;
- score = 0;
- gameover = 0;
- demo_countdown = 1000;
- level_start_wait = LEVEL_START_WAIT_START;
-
-
- /* (Create and position cities) */
-
- for (i = 0; i < NUM_CITIES; i++)
- {
- cities[i].alive = 1;
- cities[i].expl = 0;
- cities[i].shields = 1;
-
-
- /* Left vs. Right - makes room for Tux and the console */
-
- if (i < NUM_CITIES / 2)
- {
- cities[i].x = (((screen->w / (NUM_CITIES + 1)) * i) +
- ((images[IMG_CITY_BLUE] -> w) / 2));
- }
- else
- {
- cities[i].x = (screen->w -
- ((((screen->w / (NUM_CITIES + 1)) *
- (i - (NUM_CITIES / 2)) +
- ((images[IMG_CITY_BLUE] -> w) / 2)))));
- }
- }
-
- num_cities_alive = NUM_CITIES;
- num_comets_alive = 0;
-
-
- /* (Clear laser) */
-
- laser.alive = 0;
-
-
- /* Reset remaining stuff: */
-
- bkgd = NULL;
- last_bkgd = -1;
- reset_level();
-
-
- /* --- MAIN GAME LOOP!!! --- */
-
- frame = 0;
- paused = 0;
- picked_comet = -1;
- answer_digit = 0;
- doing_answer = 0;
- tux_img = IMG_TUX_RELAX1;
- tux_anim = -1;
- tux_anim_frame = 0;
- tux_same_counter = 0;
-
-
- do
- {
- frame++;
- last_time = SDL_GetTicks();
-
-
- /* Handle any incoming events: */
-
- old_tux_img = tux_img;
- tux_pressing = 0;
-
- while (SDL_PollEvent(&event) > 0)
- {
- if (event.type == SDL_QUIT)
- {
- /* Window close event - quit! */
-
- quit = 1;
- done = 1;
- }
- else if (event.type == SDL_KEYDOWN)
- {
- key = event.key.keysym.sym;
-
-
- if (key == SDLK_ESCAPE)
- {
- /* Escape key - quit! */
-
- done = 1;
- }
- else if (key == SDLK_TAB ||
- key == SDLK_p)
- {
- /* [TAB] or [P]: Pause! */
-
- paused = 1;
- }
-
-
- if (level_start_wait > 0 || demo_mode)
- {
- /* Eat other keys until level start wait has passed,
- or if game is in demo mode: */
-
- key = SDLK_UNKNOWN;
- }
-
-
- if (key >= SDLK_0 && key <= SDLK_9)
- {
- /* [0]-[9]: Add a new digit: */
-
- digits[0] = digits[1];
- digits[1] = digits[2];
- digits[2] = key - SDLK_0;
-
- tux_pressing = 1;
- }
- else if (key >= SDLK_KP0 && key <= SDLK_KP9)
- {
- /* Keypad [0]-[9]: Add a new digit: */
-
- digits[0] = digits[1];
- digits[1] = digits[2];
- digits[2] = key - SDLK_KP0;
-
- tux_pressing = 1;
- }
- else if (key == SDLK_BACKSPACE ||
- key == SDLK_CLEAR ||
- key == SDLK_DELETE)
- {
- /* [BKSP]: Clear digits! */
-
- digits[0] = 0;
- digits[1] = 0;
- digits[2] = 0;
-
- tux_pressing = 1;
- }
- else if (key == SDLK_RETURN ||
- key == SDLK_KP_ENTER ||
- key == SDLK_SPACE)
- {
- /* [ENTER]: Accept digits! */
-
- doing_answer = 1;
- }
- }
- else if (event.type == SDL_MOUSEBUTTONDOWN)
- {
- if (level_start_wait == 0 && !demo_mode)
- {
- if (event.button.x >=
- (screen->w / 2) - (images[IMG_KEYPAD]->w / 2) &&
- event.button.x <=
- (screen->w / 2) + (images[IMG_KEYPAD]->w / 2) &&
- event.button.y >=
- (screen->h / 2) - (images[IMG_KEYPAD]->h / 2) &&
- event.button.y <=
- (screen->h / 2) + (images[IMG_KEYPAD]->h / 2))
- {
- kx = (event.button.x -
- ((screen->w / 2) - (images[IMG_KEYPAD]->w / 2)));
- ky = (event.button.y -
- ((screen->h / 2) - (images[IMG_KEYPAD]->h / 2)));
-
- tux_pressing = 1;
-
-
- if (ky >= (images[IMG_KEYPAD]->h / 4) * 3)
- {
- /* Bottom row is special (has Enter key) */
-
- if (kx >= (images[IMG_KEYPAD]->w / 3))
- {
- /* "Enter" key */
-
- doing_answer = 1;
-
- tux_pressing = 0;
- }
- else
- {
- /* "0" key */
-
- digits[0] = digits[1];
- digits[1] = digits[2];
- digits[2] = 0;
- }
- }
- else
- {
- digits[0] = digits[1];
- digits[1] = digits[2];
- digits[2] = (((kx / (images[IMG_KEYPAD]->w / 3)) + 1) +
- 6 - ((ky / (images[IMG_KEYPAD]->h / 4) * 3)));
- }
- }
- }
- }
- }
-
-
-
- if (demo_mode)
- {
- /* Demo mdoe! */
-
- if (picked_comet == -1 && (rand() % 10) < 3)
- {
- /* Demo mode! Randomly pick a comet to destroy: */
-
- picked_comet = (rand() % MAX_COMETS);
-
- if (!comets[picked_comet].alive || comets[picked_comet].y < 80)
- picked_comet = -1;
- else
- {
- if (comets[picked_comet].answer >= 100)
- answer_digit = 0;
- else if (comets[picked_comet].answer >= 10)
- answer_digit = 1;
- else
- answer_digit = 2;
- }
- }
-
-
- /* Add a digit: */
-
- if (picked_comet != -1 && (frame % 5) == 0 && (rand() % 10) < 8)
- {
- tux_pressing = 1;
-
- if (answer_digit < 3)
- {
- digits[0] = digits[1];
- digits[1] = digits[2];
-
- if (answer_digit == 0)
- {
- digits[2] = comets[picked_comet].answer / 100;
- }
- else if (answer_digit == 1)
- {
- digits[2] = (comets[picked_comet].answer % 100) / 10;
- }
- else if (answer_digit == 2)
- {
- digits[2] = (comets[picked_comet].answer % 10);
- }
-
- answer_digit++;
- }
- else
- {
- /* "Press Return" */
-
- doing_answer = 1;
- picked_comet = -1;
- }
- }
-
-
- /* Count down counter: */
-
- demo_countdown--;
-
- if (demo_countdown <= 0 || num_cities_alive == 0)
- done = 1;
- }
-
-
- /* Handle answer: */
-
- if (doing_answer)
- {
- doing_answer = 0;
-
- num = (digits[0] * 100 +
- digits[1] * 10 +
- digits[2]);
-
-
- /* Pick the lowest comet which has the right answer: */
-
- lowest_y = 0;
- lowest = -1;
-
- for (i = 0; i < MAX_COMETS; i++)
- {
- if (comets[i].alive &&
- comets[i].expl == 0 &&
- comets[i].answer == num &&
- comets[i].y > lowest_y)
- {
- lowest = i;
- lowest_y = comets[i].y;
- }
- }
-
-
- /* If there was an comet with this answer, destroy it! */
-
- if (lowest != -1)
- {
- /* Destroy comet: */
-
- comets[lowest].expl = COMET_EXPL_START;
-
-
- /* Fire laser: */
-
- laser.alive = LASER_START;
-
- laser.x1 = screen->w / 2;
- laser.y1 = screen->h;
-
- laser.x2 = comets[lowest].x;
- laser.y2 = comets[lowest].y;
-
- playsound(SND_LASER);
-
-
- /* 50% of the time.. */
-
- if ((rand() % 10) < 5)
- {
- /* ... pick an animation to play: */
-
- if ((rand() % 10) < 5)
- tux_anim = IMG_TUX_YES1;
- else
- tux_anim = IMG_TUX_YAY1;
-
- tux_anim_frame = ANIM_FRAME_START;
- }
-
-
- /* Increment score: */
-
- /* [ add = 25, sub = 50, mul = 75, div = 100 ] */
- /* [ the higher the better ] */
-
- add_score(((25 * (comets[lowest].oper + 1)) *
- (screen->h - comets[lowest].y + 1)) /
- screen->h);
- }
- else
- {
- /* Didn't hit anything! */
-
- laser.alive = LASER_START;
-
- laser.x1 = screen->w / 2;
- laser.y1 = screen->h;
-
- laser.x2 = laser.x1;
- laser.y2 = 0;
-
- playsound(SND_LASER);
- playsound(SND_BUZZ);
-
- if ((rand() % 10) < 5)
- tux_img = IMG_TUX_DRAT;
- else
- tux_img = IMG_TUX_YIPE;
- }
-
-
- /* Clear digits: */
-
- digits[0] = 0;
- digits[1] = 0;
- digits[2] = 0;
- }
-
-
- /* Handle start-wait countdown: */
-
- if (level_start_wait > 0)
- {
- level_start_wait--;
-
- if (level_start_wait > LEVEL_START_WAIT_START / 4)
- tux_img = IMG_TUX_RELAX1;
- else if (level_start_wait > 0)
- tux_img = IMG_TUX_RELAX2;
- else
- tux_img = IMG_TUX_SIT;
-
- if (level_start_wait == LEVEL_START_WAIT_START / 4)
- {
- playsound(SND_ALARM);
- }
- }
-
-
- /* If Tux pressed a button, pick a new (different!) stance: */
-
- if (tux_pressing)
- {
- do
- {
- tux_img = IMG_TUX_CONSOLE1 + (rand() % 4);
- }
- while (tux_img == old_tux_img);
-
- playsound(SND_CLICK);
- }
-
-
- /* If Tux is being animated, show the animation: */
-
- if (tux_anim != -1)
- {
- tux_anim_frame--;
-
- if (tux_anim_frame < 0)
- tux_anim = -1;
- else
- tux_img = tux_anim + 1 - (tux_anim_frame / (ANIM_FRAME_START / 2));
- }
-
-
- /* Reset Tux to sitting if he's been doing nothing for a while: */
-
- if (old_tux_img == tux_img)
- {
- tux_same_counter++;
-
- if (tux_same_counter >= 20)
- {
- tux_img = IMG_TUX_SIT;
- }
- }
- else
- tux_same_counter = 0;
-
-
- /* Handle comets: */
-
- num_comets_alive = 0;
-
- for (i = 0; i < MAX_COMETS; i++)
- {
- if (comets[i].alive)
- {
- num_comets_alive++;
-
- comets[i].x = comets[i].x + 0;
- comets[i].y = comets[i].y + speed;
-
- if (comets[i].y >= (screen->h - images[IMG_CITY_BLUE]->h) &&
- comets[i].expl == 0)
- {
- /* Disable shields or destroy city: */
-
- if (cities[comets[i].city].shields)
- {
- cities[comets[i].city].shields = 0;
- playsound(SND_SHIELDSDOWN);
- }
- else
- {
- cities[comets[i].city].expl = CITY_EXPL_START;
- playsound(SND_EXPLOSION);
- }
-
- tux_anim = IMG_TUX_FIST1;
- tux_anim_frame = ANIM_FRAME_START;
-
-
- /* Destroy comet: */
-
- comets[i].expl = COMET_EXPL_START;
- }
-
-
- /* Handle comet explosion animation: */
-
- if (comets[i].expl != 0)
- {
- comets[i].expl--;
-
- if (comets[i].expl == 0)
- comets[i].alive = 0;
- }
- }
- }
-
-
- /* Handle laser: */
-
- if (laser.alive > 0)
- laser.alive--;
-
-
- /* Comet time! */
-
- if (level_start_wait == 0 && (frame % 20) == 0 &&
- gameover == 0)
- {
- if (num_attackers > 0)
- {
- /* More comets to add during this wave! */
-
- if ((rand() % 2) == 0 || num_comets_alive == 0)
- {
- add_comet();
- num_attackers--;
- }
- }
- else
- {
- if (num_comets_alive == 0)
- {
- /* Time for the next wave! */
-
- /* FIXME: End of level stuff goes here */
-
- if (num_cities_alive > 0)
- {
- /* Go on to the next wave: */
-
- wave++;
- reset_level();
- }
- else
- {
- /* No more cities! Game over! */
-
- gameover = GAMEOVER_COUNTER_START;
- }
- }
- }
- }
-
-
- /* Handle cities: */
-
- num_cities_alive = 0;
-
- for (i = 0; i < NUM_CITIES; i++)
- {
- if (cities[i].alive)
- {
- num_cities_alive++;
-
-
- /* Handle animated explosion: */
-
- if (cities[i].expl)
- {
- cities[i].expl--;
-
- if (cities[i].expl == 0)
- cities[i].alive = 0;
- }
- }
- }
-
-
- /* Handle game-over: */
-
- if (gameover > 0)
- {
- gameover--;
-
- if (gameover <= 0)
- done = 1;
- }
-
-
- /* Clear screen: */
-
- if (bkgd == NULL)
- {
- dest.x = 0;
- dest.y = 0;
- dest.w = screen->w;
- dest.h = ((screen->h) / 4) * 3;
-
- SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format,
- 64,
- 64 + ((wave * 32) % 192),
- 128 - ((wave * 16) % 128)));
-
-
- dest.x = 0;
- dest.y = ((screen->h) / 4) * 3;
- dest.w = screen->w;
- dest.h = (screen->h) / 4;
-
- SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 64, 96, 64));
- }
- else
- SDL_BlitSurface(bkgd, NULL, screen, NULL);
-
-
- /* Draw "Demo" */
-
- if (demo_mode)
- {
- dest.x = (screen->w - images[IMG_DEMO]->w) / 2;
- dest.y = (screen->h - images[IMG_DEMO]->h) / 2;
- dest.w = images[IMG_DEMO]->w;
- dest.h = images[IMG_DEMO]->h;
-
- SDL_BlitSurface(images[IMG_DEMO], NULL, screen, &dest);
- }
-
-
- /* Draw wave: */
-
- dest.x = 0;
- dest.y = 0;
- dest.w = images[IMG_WAVE]->w;
- dest.h = images[IMG_WAVE]->h;
-
- SDL_BlitSurface(images[IMG_WAVE], NULL, screen, &dest);
-
- sprintf(str, "%d", wave);
- draw_numbers(str, images[IMG_WAVE]->w + (images[IMG_NUMBERS]->w / 10));
-
-
- /* Draw score: */
-
- dest.x = (screen->w - ((images[IMG_NUMBERS]->w / 10) * 7) -
- images[IMG_SCORE]->w);
- dest.y = 0;
- dest.w = images[IMG_SCORE]->w;
- dest.h = images[IMG_SCORE]->h;
-
- SDL_BlitSurface(images[IMG_SCORE], NULL, screen, &dest);
-
- sprintf(str, "%.6d", score);
- draw_numbers(str, screen->w - ((images[IMG_NUMBERS]->w / 10) * 6));
-
-
- /* Draw comets: */
-
- for (i = 0; i < MAX_COMETS; i++)
- {
- if (comets[i].alive)
- {
- if (comets[i].expl == 0)
- {
- /* Decide which image to display: */
-
- img = IMG_COMET1 + ((frame + i) % 3);
- }
- else
- {
- img = (IMG_COMETEX2 -
- (comets[i].expl / (COMET_EXPL_START / 2)));
- }
-
-
- /* Draw it! */
-
- dest.x = comets[i].x - (images[img]->w / 2);
- dest.y = comets[i].y - images[img]->h;
- dest.w = images[img]->w;
- dest.h = images[img]->h;
-
- SDL_BlitSurface(images[img], NULL, screen, &dest);
- }
- }
-
-
- /* Draw equations: */
-
- for (i = 0; i < MAX_COMETS; i++)
- {
- if (comets[i].alive && ((comets[i].y < screen->h / 2) ||
- (frame % 8) < 6) && comets[i].expl == 0)
- {
- sprintf(str, "%d%c%d",
- comets[i].eq1,
- operchars[comets[i].oper],
- comets[i].eq2);
-
- draw_nums(str, comets[i].x, comets[i].y);
- }
- }
-
-
- /* Draw cities: */
-
- for (i = 0; i < NUM_CITIES; i++)
- {
- /* Decide which image to display: */
-
- if (cities[i].alive)
- {
- if (cities[i].expl == 0)
- img = IMG_CITY_BLUE;
- else
- img = (IMG_CITY_BLUE_EXPL5 -
- (cities[i].expl / (CITY_EXPL_START / 5)));
- }
- else
- img = IMG_CITY_BLUE_DEAD;
-
-
- /* Change image to appropriate color: */
-
- img = img + ((wave % MAX_CITY_COLORS) *
- (IMG_CITY_GREEN - IMG_CITY_BLUE));
- /* img = img + ((i % MAX_CITY_COLORS) *
- (IMG_CITY_GREEN - IMG_CITY_BLUE)); */
-
-
- /* Draw it! */
-
- dest.x = cities[i].x - (images[img]->w / 2);
- dest.y = (screen->h) - (images[img]->h);
- dest.w = (images[img]->w);
- dest.h = (images[img]->h);
-
- SDL_BlitSurface(images[img], NULL,
- screen, &dest);
-
-
- /* Draw sheilds: */
-
- if (cities[i].shields)
- {
- for (j = (frame % 3); j < images[IMG_SHIELDS]->h; j = j + 3)
- {
- src.x = 0;
- src.y = j;
- src.w = images[IMG_SHIELDS]->w;
- src.h = 1;
-
- dest.x = cities[i].x - (images[IMG_SHIELDS]->w / 2);
- dest.y = (screen->h) - (images[IMG_SHIELDS]->h) + j;
- dest.w = src.w;
- dest.h = src.h;
-
- SDL_BlitSurface(images[IMG_SHIELDS], &src, screen, &dest);
- }
- }
- }
-
-
- /* Draw laser: */
-
- if (laser.alive)
- {
- draw_line(laser.x1, laser.y1, laser.x2, laser.y2,
- 255 / (LASER_START - laser.alive),
- 192 / (LASER_START - laser.alive),
- 64);
- }
-
-
- /* Draw numeric keypad: */
-
- if (use_keypad)
- {
- dest.x = (screen->w - images[IMG_KEYPAD]->w) / 2;
- dest.y = (screen->h - images[IMG_KEYPAD]->h) / 2;
- dest.w = images[IMG_KEYPAD]->w;
- dest.h = images[IMG_KEYPAD]->h;
-
- SDL_BlitSurface(images[IMG_KEYPAD], NULL, screen, &dest);
- }
-
-
- /* Draw console & tux: */
-
- draw_console_image(IMG_CONSOLE);
-
- if (gameover > 0)
- {
- tux_img = IMG_TUX_FIST1 + ((frame / 2) % 2);
- }
-
- draw_console_image(tux_img);
-
-
- /* Draw LED digits at the top of the screen: */
-
- for (i = 0; i < 3; i++)
- {
- src.x = digits[i] * ((images[IMG_LEDNUMS]->w) / 10);
- src.y = 0;
- src.w = (images[IMG_LEDNUMS]->w) / 10;
- src.h = images[IMG_LEDNUMS]->h;
-
- dest.x = (((screen->w - (((images[IMG_LEDNUMS]->w) / 10) * 3)) / 2) +
- (i * (images[IMG_LEDNUMS]->w) / 10));
- dest.y = 4;
- dest.w = src.w;
- dest.h = src.h;
-
- SDL_BlitSurface(images[IMG_LEDNUMS], &src, screen, &dest);
- }
-
-
- /* Draw "Game Over" */
-
- if (gameover > 0)
- {
- dest.x = (screen->w - images[IMG_GAMEOVER]->w) / 2;
- dest.y = (screen->h - images[IMG_GAMEOVER]->h) / 2;
- dest.w = images[IMG_GAMEOVER]->w;
- dest.h = images[IMG_GAMEOVER]->h;
-
- SDL_BlitSurface(images[IMG_GAMEOVER], NULL, screen, &dest);
- }
-
-
- /* Swap buffers: */
-
- SDL_Flip(screen);
-
-
- /* If we're in "PAUSE" mode, pause! */
-
- if (paused)
- {
- quit = pause_game();
- paused = 0;
- }
-
-
- /* Keep playing music: */
-
- #ifndef NOSOUND
- if (use_sound)
- {
- if (!Mix_PlayingMusic())
- Mix_PlayMusic(musics[MUS_GAME + (rand() % 3)], 0);
- }
- #endif
-
-
- /* Pause (keep frame-rate event) */
-
- now_time = SDL_GetTicks();
- if (now_time < last_time + FPS)
- SDL_Delay(last_time + FPS - now_time);
- }
- while (!done && !quit);
-
-
- /* Free background: */
-
- if (bkgd != NULL)
- SDL_FreeSurface(bkgd);
-
-
-
- /* Stop music: */
- #ifndef NOSOUND
- if (use_sound)
- {
- if (Mix_PlayingMusic())
- {
- Mix_HaltMusic();
- }
- }
- #endif
-
-
- /* Return the chosen command: */
-
- return quit;
- }
-
-
- /* Reset stuff for the next level! */
-
- void reset_level(void)
- {
- char fname[1024];
- int i;
-
-
- /* Clear all comets: */
-
- for (i = 0; i < MAX_COMETS; i++)
- comets[i].alive = 0;
-
-
- /* Clear LED digits: */
-
- digits[0] = 0;
- digits[1] = 0;
- digits[2] = 0;
-
-
- /* Load random background image: */
-
- do
- {
- /* Don't pick the same one as last time... */
-
- i = rand() % NUM_BKGDS;
- }
- while (i == last_bkgd);
-
- last_bkgd = i;
-
- sprintf(fname, "%s/images/backgrounds/%d.jpg", DATA_PREFIX, i);
-
- if (bkgd != NULL)
- SDL_FreeSurface(bkgd);
-
-
- if (use_bkgd == 1)
- {
- bkgd = IMG_Load(fname);
- if (bkgd == NULL)
- {
- fprintf(stderr,
- "\nWarning: Could not load background image:\n"
- "%s\n"
- "The Simple DirectMedia error that ocurred was: %s\n",
- fname, SDL_GetError());
- use_bkgd = 0;
- }
- }
-
-
- /* Record score before this wave: */
-
- pre_wave_score = score;
-
-
- /* Set number of attackers for this wave: */
-
- num_attackers = 2 * wave; /* FIXME: Is this good? */
-
-
- /* Set speed: */
-
- speed = wave + 1;
-
- if (speed > 10)
- speed = 10;
- }
-
-
- /* Add an comet to the game (if there's room): */
-
- void add_comet(void)
- {
- int i, found;
-
-
- /* Look for a free comet slot: */
-
- found = -1;
-
- for (i = 0; i < MAX_COMETS && found == -1; i++)
- {
- if (comets[i].alive == 0)
- {
- found = i;
- }
- }
-
-
- if (found != -1)
- {
- comets[found].alive = 1;
-
-
- /* Pick a city to attack: */
-
- i = rand() % NUM_CITIES;
-
-
- /* Set in to attack that city: */
-
- comets[found].city = i;
-
-
- /* Start at the top, above the city in question: */
-
- comets[found].x = cities[i].x;
- comets[found].y = 0;
-
-
- /* Pick an operation (+, -, *, /): */
-
- do
- {
- comets[found].oper = (rand() % NUM_OPERS);
- }
- while (opers[comets[found].oper] == 0);
-
-
- if (comets[found].oper == OPER_ADD)
- {
- /* Simple addition: */
-
- comets[found].eq1 = (rand() % 10);
- comets[found].eq2 = (rand() % 10);
- comets[found].answer = comets[found].eq1 + comets[found].eq2;
- }
- else if (comets[found].oper == OPER_SUB)
- {
- /* Subtraction: */
-
- comets[found].eq1 = (rand() % 10);
-
-
- /* (No negative answers) */
- /* [ WILL PROBABLY ALLOW FOR NEG. ANS. ] */
-
- do
- {
- comets[found].eq2 = (rand() % 10);
- }
- while (comets[found].eq2 > comets[found].eq1);
-
- comets[found].answer = comets[found].eq1 - comets[found].eq2;
- }
- else if (comets[found].oper == OPER_MULT)
- {
- /* Multiplication: */
-
- comets[found].eq1 = (rand() % 10);
- comets[found].eq2 = (rand() % 10);
- comets[found].answer = comets[found].eq1 * comets[found].eq2;
- }
- else if (comets[found].oper == OPER_DIV)
- {
- /* Division: */
-
- /* (Don't divide by zero) */
-
- comets[found].eq2 = (rand() % 9) + 1;
-
-
- /* (Make sure answer will be a whole (int) number) */
-
- comets[found].eq1 = (rand() % 10) * comets[found].eq2;
-
-
- comets[found].answer = comets[found].eq1 / comets[found].eq2;
- }
- }
- }
-
-
- /* Draw numbers/symbols over the attacker: */
-
- void draw_nums(char * str, int x, int y)
- {
- int i, j, cur_x, c;
- SDL_Rect src, dest;
-
-
- /* Center around the shape */
-
- cur_x = x - ((strlen(str) * (images[IMG_NUMS]->w / (10 + NUM_OPERS)))) / 2;
-
- if (cur_x < 0)
- cur_x = 0;
-
- if (cur_x + (strlen(str) * (images[IMG_NUMS]->w / (10 + NUM_OPERS))) >=
- screen->w)
- cur_x = ((screen->w) -
- (strlen(str) * (images[IMG_NUMS]->w / (10 + NUM_OPERS))));
-
-
- /* Draw each character: */
-
- for (i = 0; i < strlen(str); i++)
- {
- c = -1;
-
-
- /* Determine which character to display: */
-
- if (str[i] >= '0' && str[i] <= '9')
- c = str[i] - '0';
- else
- {
- /* [ THIS COULD CAUSE SLOWNESS... ] */
-
- for (j = 0; j < NUM_OPERS; j++)
- {
- if (str[i] == operchars[j])
- {
- c = 10 + j;
- }
- }
- }
-
-
- /* Display this character! */
-
- if (c != -1)
- {
- src.x = c * (images[IMG_NUMS]->w / (10 + NUM_OPERS));
- src.y = 0;
- src.w = (images[IMG_NUMS]->w / (10 + NUM_OPERS));
- src.h = images[IMG_NUMS]->h;
-
- dest.x = cur_x;
- dest.y = y - images[IMG_NUMS]->h;
- dest.w = src.w;
- dest.h = src.h;
-
- SDL_BlitSurface(images[IMG_NUMS], &src,
- screen, &dest);
-
-
- /* Move the 'cursor' one character width: */
-
- cur_x = cur_x + (images[IMG_NUMS]->w / (10 + NUM_OPERS));
- }
- }
- }
-
-
- /* Draw status numbers: */
-
- void draw_numbers(char * str, int x)
- {
- int i, cur_x, c;
- SDL_Rect src, dest;
-
-
- cur_x = x;
-
-
- /* Draw each character: */
-
- for (i = 0; i < strlen(str); i++)
- {
- c = -1;
-
-
- /* Determine which character to display: */
-
- if (str[i] >= '0' && str[i] <= '9')
- c = str[i] - '0';
-
-
- /* Display this character! */
-
- if (c != -1)
- {
- src.x = c * (images[IMG_NUMBERS]->w / 10);
- src.y = 0;
- src.w = (images[IMG_NUMBERS]->w / 10);
- src.h = images[IMG_NUMBERS]->h;
-
- dest.x = cur_x;
- dest.y = 0;
- dest.w = src.w;
- dest.h = src.h;
-
- SDL_BlitSurface(images[IMG_NUMBERS], &src,
- screen, &dest);
-
-
- /* Move the 'cursor' one character width: */
-
- cur_x = cur_x + (images[IMG_NUMBERS]->w / 10);
- }
- }
- }
-
-
- /* Pause loop: */
-
- int pause_game(void)
- {
- int done, quit;
- SDL_Event event;
- SDL_Rect dest;
-
- done = 0;
- quit = 0;
-
- dest.x = (screen->w - images[IMG_PAUSED]->w) / 2;
- dest.y = (screen->h - images[IMG_PAUSED]->h) / 2;
- dest.w = images[IMG_PAUSED]->w;
- dest.h = images[IMG_PAUSED]->h;
-
- SDL_BlitSurface(images[IMG_PAUSED], NULL, screen, &dest);
- SDL_Flip(screen);
-
-
- #ifndef NOSOUND
- if (use_sound)
- Mix_PauseMusic();
- #endif
-
-
- do
- {
- while (SDL_PollEvent(&event))
- {
- if (event.type == SDL_KEYDOWN)
- done = 1;
- else if (event.type == SDL_QUIT)
- quit = 1;
- }
-
- SDL_Delay(100);
- }
- while (!done && !quit);
-
-
- #ifndef NOSOUND
- if (use_sound)
- Mix_ResumeMusic();
- #endif
-
- return (quit);
- }
-
-
-
- /* Draw a line: */
-
- void draw_line(int x1, int y1, int x2, int y2, int red, int grn, int blu)
- {
- int dx, dy, tmp;
- float m, b;
- Uint32 pixel;
- SDL_Rect dest;
-
- pixel = SDL_MapRGB(screen->format, red, grn, blu);
-
- dx = x2 - x1;
- dy = y2 - y1;
-
- putpixel(screen, x1, y1, pixel);
-
- if (dx != 0)
- {
- m = ((float) dy) / ((float) dx);
- b = y1 - m * x1;
-
- if (x2 > x1)
- dx = 1;
- else
- dx = -1;
-
- while (x1 != x2)
- {
- x1 = x1 + dx;
- y1 = m * x1 + b;
-
- putpixel(screen, x1, y1, pixel);
- }
- }
- else
- {
- if (y1 > y2)
- {
- tmp = y1;
- y1 = y2;
- y2 = tmp;
- }
-
- dest.x = x1;
- dest.y = y1;
- dest.w = 3;
- dest.h = y2 - y1;
-
- SDL_FillRect(screen, &dest, pixel);
- }
- }
-
-
- /* Draw a single pixel into the surface: */
-
- void putpixel(SDL_Surface * surface, int x, int y, Uint32 pixel)
- {
- #ifdef PUTPIXEL_RAW
- int bpp;
- Uint8 * p;
-
- /* Determine bytes-per-pixel for the surface in question: */
-
- bpp = surface->format->BytesPerPixel;
-
-
- /* Set a pointer to the exact location in memory of the pixel
- in question: */
-
- p = (Uint8 *) (surface->pixels + /* Start at beginning of RAM */
- (y * surface->pitch) + /* Go down Y lines */
- (x * bpp)); /* Go in X pixels */
-
-
- /* Assuming the X/Y values are within the bounds of this surface... */
-
- if (x >= 0 && y >= 0 && x < surface -> w && y < surface -> h)
- {
- /* Set the (correctly-sized) piece of data in the surface's RAM
- to the pixel value sent in: */
-
- if (bpp == 1)
- *p = pixel;
- else if (bpp == 2)
- *(Uint16 *)p = pixel;
- else if (bpp == 3)
- {
- if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
- {
- p[0] = (pixel >> 16) & 0xff;
- p[1] = (pixel >> 8) & 0xff;
- p[2] = pixel & 0xff;
- }
- else
- {
- p[0] = pixel & 0xff;
- p[1] = (pixel >> 8) & 0xff;
- p[2] = (pixel >> 16) & 0xff;
- }
- }
- else if (bpp == 4)
- {
- *(Uint32 *)p = pixel;
- }
- }
- #else
- SDL_Rect dest;
-
- dest.x = x;
- dest.y = y;
- dest.w = 3;
- dest.h = 4;
-
- SDL_FillRect(surface, &dest, pixel);
- #endif
- }
-
-
- /* Draw image at lower center of screen: */
-
- void draw_console_image(int i)
- {
- SDL_Rect dest;
-
- dest.x = (screen->w - images[i]->w) / 2;
- dest.y = (screen->h - images[i]->h);
- dest.w = images[i]->w;
- dest.h = images[i]->h;
-
- SDL_BlitSurface(images[i], NULL, screen, &dest);
- }
-
-
- /* Increment score: */
-
- void add_score(int inc)
- {
- score += inc;
- }
-
-
-